package org.robotfish.optimize;

import static org.junit.Assert.*;
import static java.lang.Math.*;

import java.io.IOException;

import org.ejml.data.DenseMatrix64F;
import org.ejml.ops.MatrixFeatures;
import org.ejml.simple.SimpleMatrix;
import org.junit.Test;

public class MDTest {
	MDFunction fcn = new MDFunction()
	{
		public int argumentLength() {
			return 2;
		}
		public double f (double[] x) {
			return 2.0 - gaussian (x[0]) - gaussian (x[1]);
		}
		private double gaussian (double x) {
	      
	      double d = x - 0.5;
	      return exp (-d*d);
	      }
	};

	@Test
	public void test() {
		MDMinimizationDownhillSimplex minimizer =  new MDMinimizationDownhillSimplex (fcn);
		//minimizer.setSimplex (new double[] {0.0, 0.0}, 0.1);
		minimizer.minimize();
		assertArrayEquals(minimizer.getMinX(), new double[]{0.5, 0.5}, 1e-5);
	}
	
	@Test
	public void testMatrix() throws IOException {
		double[] v = new double[]{
			1.5, 0.5, 0.1,
			0.5, 3.1, 2.5,
			0.1, 2.5, 5.0
		};
		SimpleMatrix m = new SimpleMatrix(3, 3, true, v);
		SimpleMatrix minv = m.invert();
		//System.out.println( minv );
		
		// writing csv to disk:
		//MatrixIO.saveCSV(m.getMatrix(), "matrix-test.csv");
		// can be read in R by:
		// X=read.table("matrix-test.csv", sep=" ", skip=1, header=F)
		// X=X[,-ncol(X)]
		
		// scalar product:
		SimpleMatrix r1 = m.extractVector(true, 1);
		System.out.println( r1 );
		System.out.println( r1.dot(r1) );
		
		// for fast resizing create a large matrix and then reshape it to a small one
		int n=8000;
		DenseMatrix64F A = new DenseMatrix64F(n, 6);
		A.reshape(1, 6);
		A.set(0, 0, 1.5);
		A.set(0, 5, 2.5);
		for (int i=2; i<n; i++) {
			A.reshape(i+1, 6, true);
		}
		
	}
	
	@Test
	public void matrixReshape() {
		double[] data = {
			1.0, 2.0, 3.0, 4.0,
			5.0, 6.0, 7.0, 8.0
		};
		DenseMatrix64F m = new DenseMatrix64F(2, 4, true, data);
		//SimpleMatrix m = new SimpleMatrix(2, 4, true, data);
		m.reshape(3, 4, true);
		m.print();
		
		double[] data2 = {
			1.0, 2.0, 3.0, 4.0,
			5.0, 6.0, 7.0, 8.0,
			  0,   0,   0,   0
		};
		DenseMatrix64F m2 = new DenseMatrix64F(3, 4, true, data2);
		assertTrue( MatrixFeatures.isEquals(m, m2, 1e-6) );
		
	}

}
